##
# \file counting.py
#

# --  Python imports  --
# -- End Python imports --

# --  Pybrain imports  --
# -- End Pybrain imports --

# --  Project imports  --
# -- End Project imports --

##
# \class CardCounter
# \details This class is capable of performing the following types of card counting:
# - KO Count
# - HI/LOW Count
# - HI Opt 1 Count
# - HI Opt 2 Count
# - Zen Count
# - Omega II Count
class CardCounter:

    ## \var KO_COUNT
    # Index in the tuple returned by getAllCounts for the count: KO Count
    KO_COUNT       = 0

    ## \var HI_LOW_COUNT
    # Index in the tuple returned by getAllCounts for the count: HI/LOW Count
    HI_LOW_COUNT   = 1

    ## \var HI_OPT1_COUNT
    # Index in the tuple returned by getAllCounts for the count: HI Opt 1 Count
    HI_OPT1_COUNT  = 2

    ## \var HI_OPT2_COUNT
    # Index in the tuple returned by getAllCounts for the count: HI Opt 2 Count
    HI_OPT2_COUNT  = 3

    ## \var ZEN_COUNT
    # Index in the tuple returned by getAllCounts for the count: Zen Count
    ZEN_COUNT      = 4

    ## \var OMEGA_II_COUNT
    # Index in the tuple returned by getAllCounts for the count: Omega II Count
    OMEGA_II_COUNT = 5

    ##
    # \details Class constructor that sets all counts to zero (0).
    def __init__(self):
        self.reset()

    ##
    # \details Updates the following card counting techniques:
    # - KO Count
    # - HI/LOW Count
    # - HI Opt 1 Count
    # - HI Opt 2 Count
    # - Zen Count
    # - Omega II Count
    #
    # \pre none
    # \post all counters are updated with the current count.
    # \param value The value of the observed card.
    # \return none
    def update(self, value):
        self.updateKO(value)
        self.updateHiLow(value)
        self.updateHiOpt1(value)
        self.updateHiOpt2(value)
        self.updateZen(value)
        self.updateOmegaII(value)

    ##
    # \details Returns the current count as a tuple for the following techniques:
    # - KO Count
    # - HI/LOW Count
    # - HI Opt 1 Count
    # - HI Opt 2 Count
    # - Zen Count
    # - Omega II Count
    #
    # \pre none
    # \post none
    # \return Tuple of the current card counts.
    def getAllCounts(self):
        return (self.KO_Count, self.HiLow_Count, self.HiOpt1_Count, self.HiOpt2_Count, self.Zen_Count, self.OmegaII_Count)

    ##
    # \details Resets all counts to zero (0).
    def reset(self):
        ## \var KO_Count
        # Current value for the KO Count Technique.
        self.KO_Count      = 0

        ## \var HiLow_Count
        # Current value for the HI/LOW Count Technique.
        self.HiLow_Count   = 0

        ## \var HiOpt1_Count
        # Current value for the HI Opt 1 Count Technique.
        self.HiOpt1_Count  = 0

        ## \var HiOpt2_Count
        # Current value for the HI Opt 2 Count Technique.
        self.HiOpt2_Count  = 0

        ## \var Zen_Count
        # Current value for the Zen Count Technique.
        self.Zen_Count     = 0

        ## \var OmegaII_Count
        # Current value for the Omega II Count Technique.
        self.OmegaII_Count = 0

    ##
    # \details KO Count Description:
    # - Two/Three/Four/Five/Six/Seven = +1
    # - Eight/Nine = 0
    # - Ten/Jack/Queen/King/Ace = -1
    #
    # \pre none
    # \post \link KO_Count KO_Count \endlink is updated with the current count.
    # \param value The value of the observed card.
    # \return none
    def updateKO(self, value):
        if (value == 8) or (value == 9):
            self.KO_Count += 0
        elif (value >= 2) and (value <= 7):
            self.KO_Count += 1
        elif (value == 10) or (value == 11):
            self.KO_Count += -1
        else:
            assert False, "Unknown card value observed!"

    ##
    # \details HI/LOW Count Description:
    # - Two/Three/Four/Five/Six = +1
    # - Seven/Eight/Nine = 0
    # - Ten/Jack/Queen/King/Ace = -1
    #
    # \pre none
    # \post \link HiLow_Count HiLow_Count \endlink is updated with the current count.
    # \param value The value of the observed card.
    # \return none
    def updateHiLow(self, value):
        if (value >= 7) and (value <= 9):
            self.HiLow_Count += 0
        elif (value >= 2) and (value <= 6):
            self.HiLow_Count += 1
        elif (value == 10) or (value == 11):
            self.HiLow_Count += -1
        else:
            assert False, "Unknown card value observed!"

    ##
    # \details HI Opt 1 Count Description:
    # - Two/Seven/Eight/Nine/Ace = 0
    # - Three/Four/Five/Six = +1
    # - Ten/Jack/Queen/King = -1
    #
    # \pre none
    # \post \link HiOpt1_Count HiOpt1_Count \endlink is updated with the current count.
    # \param value The value of the observed card.
    # \return none
    def updateHiOpt1(self, value):
        if (value == 2) or (value == 11) or ((value >= 7) and (value <= 9)):
            self.HiOpt1_Count += 0
        elif (value >= 3) and (value <= 6):
            self.HiOpt1_Count += 1
        elif (value == 10):
            self.HiOpt1_Count += -1
        else:
            assert False, "Unknown card value observed!"

    ##
    # \details HI Opt 2 Count Description:
    # - Ace = 0
    # - Two/Three = +1
    # - Four/Five = +2
    # - Six/Seven = +1
    # - Eight/Nine = 0
    # - Ten/Jack/Queen/King = -2
    #
    # \pre none
    # \post \link HiOpt2_Count HiOpt2_Count \endlink is updated with the current count.
    # \param value The value of the observed card.
    # \return none
    def updateHiOpt2(self, value):
        if (value == 11) or (value == 8) or (value == 9):
            self.HiOpt2_Count += 0
        elif (value == 2) or (value == 3):
            self.HiOpt2_Count += 1
        elif (value == 4) or (value == 5):
            self.HiOpt2_Count += 2
        elif (value == 6) or (value == 7):
            self.HiOpt2_Count += 1
        elif (value == 10):
            self.HiOpt2_Count += -2
        else:
            assert False, "Unknown card value observed!"

    ##
    # \details Zen Count Description:
    # - Two/Three/Seven = +1
    # - Four/Five/Six = +2
    # - Eight/Nine = 0
    # - Ten/Jack/Queen/King = -2
    # - Ace = -1
    #
    # \pre none
    # \post \link Zen_Count Zen_Count \endlink is updated with the current count.
    # \param value The value of the observed card.
    # \return none
    def updateZen(self, value):
        if (value == 2) or (value == 3) or (value == 7):
            self.Zen_Count += 1
        elif (value >= 4) and (value <= 6):
            self.Zen_Count += 2
        elif (value == 8) or (value == 9):
            self.Zen_Count += 0
        elif (value == 10):
            self.Zen_Count += -2
        elif (value == 11):
            self.Zen_Count += -1
        else:
            assert False, "Unknown card value observed!"

    ##
    # \details Omega II Count Description:
    # - Ace = 0
    # - Two/Three = +1
    # - Four/Five/Six = +2
    # - Seven = +1
    # - Eight = 0
    # - Nine = -1
    # - Ten/Jack/Queen/King = -2
    #
    # \pre none
    # \post \link OmegaII_Count OmegaII_Count \endlink is updated with the current count.
    # \param value The value of the observed card.
    # \return none
    def updateOmegaII(self, value):
        if (value == 8) or (value == 11):
            self.OmegaII_Count += 0
        elif (value == 2) or (value == 3) or (value == 7):
            self.OmegaII_Count += 1
        elif (value >= 4) and (value <= 6):
            self.OmegaII_Count += 2
        elif (value == 9):
            self.OmegaII_Count += -1
        elif (value == 10):
            self.OmegaII_Count += -2
        else:
            assert False, "Unknown card value observed!"
